package cn.huiyunche.base.service.interfaces.impl;

import cn.huiyunche.base.service.framework.utils.HYCUtils;
import cn.huiyunche.base.service.interfaces.DrawService;
import cn.huiyunche.base.service.interfaces.UserService;
import cn.huiyunche.base.service.mappers.CAwardAddressMapper;
import cn.huiyunche.base.service.mappers.CAwardDrawrecordMapper;
import cn.huiyunche.base.service.mappers.CAwardMapper;
import cn.huiyunche.base.service.mappers.CAwardRecordMapper;
import cn.huiyunche.base.service.model.*;
import cn.huiyunche.base.service.utils.DateUtils;
import cn.huiyunche.base.service.vo.CAwardRecordVo;
import cn.huiyunche.base.service.vo.DrawAddressVo;
import cn.huiyunche.base.service.vo.Result;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class DrawServiceImpl implements DrawService {

    private static final Logger LOGGER = LoggerFactory.getLogger(DrawServiceImpl.class);

    /**
     * 抽奖日期段
     */
    private final int[] drawDayList = {5, 10};

    @Autowired
    private CAwardMapper cAwardMapper = null;

    @Autowired
    private CAwardDrawrecordMapper cAwardDrawrecordMapper = null;

    @Autowired
    private CAwardRecordMapper cAwardRecordMapper = null;

    @Autowired
    private CAwardAddressMapper cAwardAddressMapper = null;

    @Autowired
    private UserService userService = null;

    @Override
    public Result<String> checkDrawDays(String drawUserId) {
        LOGGER.info("checkDrawDays param : {}", drawUserId);
        Result<String> r = new Result<>(false);
        r.setMessage("每月" + drawDayList[0] + "-" + drawDayList[1] + "号为抽奖日期");
        String drawUserIdInCache = HYCUtils.getDrawUserCodeCache(drawUserId);
        if (null == drawUserIdInCache || !drawUserIdInCache.equals(drawUserId)) {
            r.setMessage("用户信息过期，请重新打开活动页面");
            return r;
        }
        int thisDay = NumberUtils.toInt(DateUtils.getCurrentZeroDate("dd"));
        // 抽奖日期
        if (drawDayList[0] <= thisDay && drawDayList[1] >= thisDay) {
            r.setMessage(null);
            r.setSuccess(true);
        }
        return r;
    }

    @Override
    public Result<List<CAward>> getDrawList() {
        Result<List<CAward>> r = new Result<>(false);
        CAwardExample cae = new CAwardExample();
        cae.createCriteria().andCreateTimeBetween(DateUtils.getFirstDay4Month(), DateUtils.getLastDay4Month());
        r.setSuccess(true);
        r.setData(this.getCAwardMapper().selectByExample(cae));
        return r;
    }

    @Override
    public Result<Object> turnplateDraw(String drawUserId) {
        LOGGER.info("turnplateDraw param : {}", drawUserId);
        Result<Object> r = new Result<>(false);
        // 用户合法性
        String drawUserIdInCache = HYCUtils.getDrawUserCodeCache(drawUserId);
        if (null == drawUserIdInCache || !drawUserIdInCache.equals(drawUserId)) {
            r.setMessage("用户信息过期，请重新打开活动页面");
            return r;
        }
        // 是否参与过抽奖
        if (this.isDraw(drawUserIdInCache)) {
            r.setMessage("你本月已参与抽奖，敬请关注下月抽奖");
            return r;
        }
        // 奖品数量
        List<CAward> drawList = this.enableDrawList();
        if (drawList.size() <= 0) {
            r.setMessage("本月抽奖已抽完，敬请关注下月抽奖");
            return r;
        }
        // 本月奖品列表
        List<CAward> dl = this.getDrawList().getData();
        int ranDomCount = (dl.size() + 1) * 2;
        // 获取随机码，设置奖品
        int ranDom = 1 + (int) (Math.random() * ranDomCount);
        // 设置抽奖数据
        this.setMyDraw(dl, ranDom, r, drawUserIdInCache);
        if (!r.isSuccess()) {
            return r;
        }
        r.setData(ranDom);
        r.setSuccess(true);
        return r;
    }

    @Override
    public Result<Object> addressDraw(String drawUserId, DrawAddressVo dav) {
        LOGGER.info("addressDraw params : {}, {}", drawUserId, dav);
        Result<Object> r = new Result<>(false);
        String drawUserIdInCache = HYCUtils.getDrawUserCodeCache(drawUserId);
        if (null == drawUserIdInCache || !drawUserIdInCache.equals(drawUserId)) {
            r.setMessage("用户信息过期，请重新打开活动页面");
            return r;
        }
        CAwardRecordExample care = new CAwardRecordExample();
        care.createCriteria().andUserIdEqualTo(NumberUtils.toLong(HYCUtils.decryptBankCard(drawUserId)))
                .andCreateTimeBetween(DateUtils.getFirstDay4Month(), DateUtils.getLastDay4Month());
        List<CAwardRecord> list = this.getCAwardRecordMapper().selectByExample(care);
        if (list.size() <= 0) {
            r.setMessage("请先参加抽奖");
            return r;
        }
        // 邮寄地址
        CAwardAddressExample caae = new CAwardAddressExample();
        caae.createCriteria().andCreateTimeBetween(DateUtils.getFirstDay4Month(), DateUtils.getLastDay4Month())
                .andUserIdEqualTo(NumberUtils.toLong(HYCUtils.decryptBankCard(drawUserId)));
        List<CAwardAddress> alist = this.getCAwardAddressMapper().selectByExample(caae);
        if (alist.size() > 0) {
            r.setMessage("您已填写邮寄地址");
            return r;
        }

        // 保存中奖地址信息
        CAwardRecord car = list.get(0);
        CAwardAddress caa = new CAwardAddress();
        BeanCopier beanCopierT = BeanCopier.create(DrawAddressVo.class, CAwardAddress.class, false);
        beanCopierT.copy(dav, caa, null);
        caa.setAwardId(car.getAwardId());
        caa.setAwardName(car.getAwardName());
        caa.setCreateTime(new Date());
        caa.setUserId(NumberUtils.toLong(HYCUtils.decryptBankCard(drawUserId)));
        this.getCAwardAddressMapper().insert(caa);
        r.setMessage("地址提交成功");
        r.setSuccess(true);
        return r;
    }

    @Override
    public Result<List<CAwardRecordVo>> getEnableDrawList() {
        Result<List<CAwardRecordVo>> r = new Result<>(true);
        CAwardRecordExample care = new CAwardRecordExample();
        care.createCriteria().andCreateTimeBetween(DateUtils.getFirstDay4Month(), DateUtils.getLastDay4Month());
        List<CAwardRecord> list = this.getCAwardRecordMapper().selectByExample(care);
        List<CAwardRecordVo> cList = new ArrayList<>();
        for (CAwardRecord car : list) {
            SUser su = this.getUserService().getById(car.getUserId());
            String phone = su.getPhone();
            CAward ca = this.getCAwardMapper().selectByPrimaryKey(car.getAwardId());
            CAwardRecordVo carv = new CAwardRecordVo();
            carv.setAwardName(car.getAwardName());
            carv.setPhone(phone.substring(0, 3) + "*****" + phone.substring(phone.length() - 3, phone.length()));
            carv.setUsername(su.getRealName());
            carv.setAwardLevel(ca.getAwardLevel());
            cList.add(carv);
        }
        r.setData(cList);
        return r;
    }

    /**
     * 设置奖品
     *
     * @param dl     奖品列表
     * @param ranDom 随机数
     */
    private void setMyDraw(List<CAward> dl, int ranDom, Result<Object> r, String drawUserId) {
        this.setUserDrawLog(drawUserId);
        int drawCount = dl.size();
        int ranDom4List = ranDom;
        CAward cw = null;
        if (ranDom > drawCount) {
            if (ranDom % (drawCount + 1) == 0) {
                r.setMessage("很遗憾，本次未抽中奖品");
                r.setSuccess(false);
                return;
            }
            ranDom4List = ranDom / 2;
        }
        cw = dl.get(ranDom4List - 1);
        CAward nca = this.getCAwardMapper().selectByPrimaryKey(cw.getId());
        if (nca.getAwardCount() <= 0) {
            r.setMessage("哎呦，奖品已抽完");
            r.setSuccess(false);
            return;
        }
        // 插入奖品表，减去奖品表中数量
        this.resetDrawCount(nca);
        this.setDrawRecode(nca, drawUserId);
        r.setMessage("恭喜你，抽中" + nca.getAwardLevel() + " " + nca.getAwardName());
        r.setSuccess(false);

    }

    /**
     * 重置奖品数量
     *
     * @param nca
     */
    private void resetDrawCount(CAward nca) {
        nca.setAwardCount(nca.getAwardCount() - 1);
        this.getCAwardMapper().updateByPrimaryKey(nca);
    }

    /**
     * 添加获奖记录表
     *
     * @param nca        奖品对象
     * @param drawUserId 用户id
     */
    private void setDrawRecode(CAward nca, String drawUserId) {
        SUser su = this.getUserService().getById(NumberUtils.toLong(HYCUtils.decryptBankCard(drawUserId)));
        CAwardRecord car = new CAwardRecord();
        car.setAwardId(nca.getId());
        car.setAwardName(nca.getAwardName());
        car.setCreateTime(new Date());
        car.setUserId(su.getId());
        car.setUsername(su.getRealName());
        this.getCAwardRecordMapper().insert(car);
    }

    /**
     * 写入抽奖日志
     *
     * @param drawUserId 用户id
     */
    private void setUserDrawLog(String drawUserId) {
        CAwardDrawrecord cad = new CAwardDrawrecord();
        cad.setCreateTime(new Date());
        cad.setDrawnum(1);
        cad.setUserId(NumberUtils.toLong(HYCUtils.decryptBankCard(drawUserId)));
        this.getCAwardDrawrecordMapper().insert(cad);
    }

    /**
     * 获取可用奖品列表
     *
     * @return 结果集
     */
    private List<CAward> enableDrawList() {
        CAwardExample cae = new CAwardExample();
        cae.createCriteria().andCreateTimeBetween(DateUtils.getFirstDay4Month(), DateUtils.getLastDay4Month())
                .andAwardCountGreaterThan(0);
        return this.getCAwardMapper().selectByExample(cae);
    }

    /**
     * 检查本月是否抽过奖品
     *
     * @param drawUserId 用户id
     * @return 是否抽过奖品
     */
    private boolean isDraw(String drawUserId) {
        CAwardDrawrecordExample cade = new CAwardDrawrecordExample();
        cade.createCriteria().andUserIdEqualTo(NumberUtils.toLong(HYCUtils.decryptBankCard(drawUserId)))
                .andCreateTimeBetween(DateUtils.getFirstDay4Month(), DateUtils.getLastDay4Month());
        List<CAwardDrawrecord> list = this.getCAwardDrawrecordMapper().selectByExample(cade);
        return list.size() > 0;
    }

    private CAwardMapper getCAwardMapper() {
        return this.cAwardMapper;
    }

    private CAwardDrawrecordMapper getCAwardDrawrecordMapper() {
        return this.cAwardDrawrecordMapper;
    }

    private CAwardRecordMapper getCAwardRecordMapper() {
        return this.cAwardRecordMapper;
    }

    private CAwardAddressMapper getCAwardAddressMapper() {
        return this.cAwardAddressMapper;
    }

    private UserService getUserService() {
        return this.userService;
    }

}
